using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using Abs.Core.DAL.AdoNet;
using Abs.Core.DAL.EntityFramework;
using Abs.Core.Models.Booking;
using Abs.Core.Models.Room;

namespace Abs.Core.Management
{
    public class AppointmentManagement
    {
        internal AppointmentManagement()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roomId"></param>
        /// <param name="userEmail"></param>
        /// <param name="startDateTime">
        ///     Example of the startDateTime format is "16/02/2008 13:15:12"
        /// </param>
        /// <param name="endDateTime">
        ///     Example of the endDateTime format is "16/02/2008 13:15:12"
        /// </param>
        /// <param name="comment"></param>
        [DataObjectMethod(DataObjectMethodType.Insert)]
        public bool CreateAppointment(int roomId, string userEmail,
            string startDateTime, string endDateTime, string comment)
        {
            var startTime = DateTime.Parse(startDateTime);
            var endTime = DateTime.Parse(endDateTime);

            using(var appointmentRepository = new AppointmentRepository())
            {
                var isBookingOverlapped = appointmentRepository.IsBookingOverlapped(roomId,
                                                                            startTime, 
                                                                            endTime);
                if (isBookingOverlapped == true)
                    return false;

                return appointmentRepository.Create(new Appointment
                                                    {
                                                        RoomId = roomId,
                                                        UserEmail = userEmail,
                                                        StartTime = startTime,
                                                        EndTime = endTime,
                                                        Comment = comment
                                                    });
            }//end of using(var appointmentRepository = new AppointmentRepository())
        }//end of public bool CreateAppointment(...)

        /// <summary>
        /// 
        /// </summary>
        /// <param name="appointmentId"></param>
        /// <param name="roomId"></param>
        /// <param name="userEmail"></param>
        /// <param name="startDateTime">
        ///     Example of the startDateTime format is "16/02/2008 13:15:12"
        /// </param>
        /// <param name="endDateTime">
        ///     Example of the endDateTime format is "16/02/2008 13:15:12"
        /// </param>
        /// <param name="comment"></param>
        /// <returns></returns>
        [DataObjectMethod(DataObjectMethodType.Update)]
        public bool UpdateAppointment(int appointmentId, int roomId, 
            string userEmail, string startDateTime, string endDateTime, 
            string comment)
        {
            var startTime = DateTime.Parse(startDateTime);
            var endTime = DateTime.Parse(endDateTime);

            using(var appointmentRepository = new AppointmentRepository())
            {
                var isBookingOverlapped = appointmentRepository.IsBookingOverlapped(roomId,
                                                                            startTime,
                                                                            endTime,
                                                                            appointmentId);
                if (isBookingOverlapped == true)
                    return false;

                return appointmentRepository.Update(new Appointment
                                                    {
                                                        AppointmentId = appointmentId,
                                                        RoomId = roomId,
                                                        UserEmail = userEmail,
                                                        StartTime = startTime,
                                                        EndTime = endTime,
                                                        Comment = comment
                                                    });
            }//end of using(var appointmentRepository = new AppointmentRepository())
        }//end of public bool UpdateAppointment(...)

        [DataObjectMethod(DataObjectMethodType.Select)]
        public Appointment SelectAppointment(int appointmentId)
        {
            using(var appointmentRepository = new AppointmentRepository())
            {
                return appointmentRepository.Select(new object[] {appointmentId});
            }//end of using(var appointmentRepository = new AppointmentRepository())
        }//end of public Appointment SelectAppointment()

        [DataObjectMethod(DataObjectMethodType.Fill)]
        public IList<Appointment> SelectAllAppointments()
        {
            using(var appointmentRepository = new AppointmentRepository())
            {
                return appointmentRepository.SelectAll();
            }//end of using(var appointmentRepository = new AppointmentRepository())
        }//end of public IList<Appointment> SelectAllAppointments()

        [DataObjectMethod(DataObjectMethodType.Delete)]
        public bool DeleteAppointment(int appointmentId)
        {
            using(var appointmentRepository = new AppointmentRepository())
            {
                return appointmentRepository.Delete(new object[] {appointmentId});
            }//end of using(var appointmentRepository = new AppointmentRepository())
        }//end of public bool DeleteAppointment(int appointmentId)

        /// <summary>
        /// 
        /// </summary>
        /// <param name="date">
        ///     Please refer to MSDN Document on Date.Parse to see
        ///     what kind of date format is accepted.
        ///     http://msdn.microsoft.com/en-us/library/1k1skd40.aspx
        /// </param>
        /// <returns></returns>
        [DataObjectMethod(DataObjectMethodType.Fill)]
        public IList<Appointment> GetAppointmentsOnDate(string date)
        {
            using(var appointmentRepository = new AppointmentRepository())
            {
                return appointmentRepository.GetAppointmentOnDate(DateTime.Parse(date));
                
            }//end of using(var appointmentRepository = new AppointmentRepository())
        }//end of public IList<Appointment> GetAppointmentsOnDate(string date)

        /// <summary>
        ///     This function is used for get the availability rooms on particular 
        ///     date.
        /// </summary>
        /// <param name="date">
        ///     Example of the date format is "16/02/2008"
        /// </param>
        /// <returns></returns>
        public IDictionary<int, RoomAvailability> GetAvailableRoomsOnDate(string date)
        {
            var dateTime = DateTime.Parse(date);
            var dayId = (int) dateTime.DayOfWeek;
            var roomManagement = Manage.Room;
            var roomSchedules = roomManagement.GetRoomsOnDay(dayId);
            var appointments = this.GetAppointmentsOnDate(date);
            var availableRooms = new Dictionary<int, RoomAvailability>();

            foreach(var roomSchedule in roomSchedules)
            {
                var roomName = roomManagement.SelectRoom(roomSchedule.RoomId).Name;
                availableRooms.Add(roomSchedule.RoomId, new RoomAvailability
                                                        {
                                                            RoomId = roomSchedule.RoomId,
                                                            RoomName = roomName,
                                                            StartTime = roomSchedule.StartTime,
                                                            EndTime = roomSchedule.EndTime
                                                        });
                availableRooms[roomSchedule.RoomId].InitIsAvailableAtTime();
            }//end of foreach(var roomSchedule in roomSchedules)

            foreach (var appointment in appointments)
            {
                var startHour = appointment.StartTime.Hour;
                var endHour = appointment.EndTime.Hour;

                for (var hour = startHour; hour < endHour; hour++)
                    availableRooms[appointment.RoomId].IsAvailableAtTime[hour] = false;
            }//end of foreach (var appointment in appointments)
            return availableRooms;
        }//end of public IList<RoomAvailability> GetAvailableRoomOnDate()
    }//end of class AppointmentManagement()
}//end of namespace ABS.Management
